package com.github.common.extend.demo.util.excel.dynamic;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.util.ConverterUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;

/**
 * 带自定义标题的实体类型加载
 * @author wangjj7
 * @date 2023/9/7
 * @description
 */
public class DynamicTitleReadListener<K ,T extends DynamicTitleRow<K>> implements ReadListener<T> {

    /**
     * 包含的自定义标题元数据
     */
    private final List<DynamicTitleDefine<K>> dynamicTitleDefines;

    /**
     * 自定义标题列下标与自定义标题元数据映射
     */
    private Map<Integer ,DynamicTitleDefine<K>> dynamicTitleIndex2DefineMap = Collections.EMPTY_MAP;

    public DynamicTitleReadListener(List<DynamicTitleDefine<K>> dynamicTitleDefines) {
        this.dynamicTitleDefines = dynamicTitleDefines == null ? Collections.EMPTY_LIST : dynamicTitleDefines;
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context)
    {
        if (CollectionUtils.isEmpty(dynamicTitleDefines)){
            return;
        }
        Map<Integer, String> index2NameMap = ConverterUtils.convertToStringMap(headMap, context);

        Map<String ,Integer> name2IndexMap = new HashMap<>((int) (index2NameMap.size() / 0.75) + 1);
        for (Map.Entry<Integer, String> entry : index2NameMap.entrySet()) {
            Integer colIndex = entry.getKey();
            String colName = entry.getValue();
            name2IndexMap.put(colName ,colIndex);
        }

        dynamicTitleIndex2DefineMap = new HashMap<>();
        for (DynamicTitleDefine<K> dynamicTitleDefine : dynamicTitleDefines) {
            Integer dynamicTitleIndex = name2IndexMap.get(dynamicTitleDefine.getName());
            if (dynamicTitleIndex != null){
                dynamicTitleIndex2DefineMap.put(dynamicTitleIndex ,dynamicTitleDefine);
            }
        }
    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        //开始解析数据
        parseDynamicTitleValues(data ,context.readRowHolder());
    }

    //解析自定义标题值
    private void parseDynamicTitleValues(T data ,ReadRowHolder readRowHolder) {
        Map<Integer, Cell> cellMap = readRowHolder.getCellMap();
        List<DynamicTitleCell<K>> dynamicTitleCells = new ArrayList<>();
        data.setDynamicTitleCells(dynamicTitleCells);
        for (Map.Entry<Integer, DynamicTitleDefine<K>> entry : dynamicTitleIndex2DefineMap.entrySet()) {
            Integer dynamicTitleIndex = entry.getKey();
            DynamicTitleDefine<K> dynamicTitleDefine = entry.getValue();
            Cell cell = cellMap.get(dynamicTitleIndex);
            if (cell == null) {
                continue;
            }
            if (cell instanceof ReadCellData) {
                String value = convert(((ReadCellData<?>) cell) ,dynamicTitleDefine);
                if (StringUtils.isNotBlank(value)) {
                    DynamicTitleCell<K> dynamicTitleCell = new DynamicTitleCell();
                    dynamicTitleCell.setName(dynamicTitleDefine.getName());
                    dynamicTitleCell.setKey(dynamicTitleDefine.getKey());
                    dynamicTitleCell.setValue(value);
                    dynamicTitleCells.add(dynamicTitleCell);
                }
            }
        }
    }

    private String convert(ReadCellData cellData ,DynamicTitleDefine<K> dynamicTitleDefine){
        //todo 类型适配，暂不需要
        CellDataTypeEnum type = cellData.getType();
        if (CellDataTypeEnum.STRING.equals(type) || CellDataTypeEnum.RICH_TEXT_STRING.equals(type)
                || CellDataTypeEnum.DIRECT_STRING.equals(type)){
            return cellData.getStringValue();
        }else if (CellDataTypeEnum.NUMBER.equals(type)){
            return String.valueOf(cellData.getNumberValue());
        }else if (CellDataTypeEnum.BOOLEAN.equals(type)){
            return String.valueOf(cellData.getBooleanValue());
        }else if (CellDataTypeEnum.DATE.equals(type)){
            return String.valueOf(cellData.getDataFormatData().getFormat());
        }
        return "";
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

}
